/*
    RExLib project, file utcpserver.cpp
    Copyright (C) 2012  Sarvaritdinov Ravil ra9oaj@gmail.com

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/


#include "rserver.h"

namespace rex{

RServer::RServer()
{
    _max_clnt = 0;
    _errno = 0;
    _list_state = 0;
    _host = 0;
    _port = 0;
    insoc = 0;
    events = 0;
    _stop_flag = false;
    efd = 0;
}

RServer::~RServer()
{
    if(_host)
        free(_host);

    if(insoc)
        delete insoc;

    if(events)
        free(events);
}

bool RServer::listenHostPort(char* host, uint16_t port)
{
    _stop_flag = false;
    memset (&hints, 0, sizeof (struct addrinfo));

    if(_af == RAbstractSocket::RS_INET || _af == RAbstractSocket::RS_INET6)
        hints.ai_family = AF_UNSPEC;
    else if( _af == RAbstractSocket::RS_UNIX)
        hints.ai_family = AF_UNIX;
    else
    {
        _errno = SE_AF;
        return false;
    }

    if(_pf == RAbstractSocket::RS_STREAM)
        hints.ai_protocol = SOCK_STREAM;
    else if(_pf == RAbstractSocket::RS_DGRAM)
        hints.ai_protocol = SOCK_DGRAM;
    else if(_pf == RAbstractSocket::RS_RAW)
        hints.ai_protocol = SOCK_RAW;
    else
    {
        _errno = SE_PF;
        return false;
    }

    hints.ai_flags = AI_PASSIVE;
    struct addrinfo *res;
    char prt[6];
    sprintf(prt,"%d",port);
    if(getaddrinfo(host,prt,&hints,&res));

    if(!insoc)
    {
        insoc = new RTcpSocket();
        /*insoc->setAddressFamily(_af);
        insoc->setProtocolFamily(_pf);
        if(!insoc->createSocket());
        {
            _errno = SE_CREATESOCKET;
            delete insoc;
            insoc = 0;
            return false;
        }*/
    }

    if(bind(insoc->socketFd(),hints.ai_addr,hints.ai_addrlen))
    {
        insoc->closeSocket();
        delete insoc;
        insoc = 0;
        _errno = SE_BIND;
        return false;
    }
    freeaddrinfo(res);

    insoc->setNonBlock(true);

    int _max = (_max_clnt != 0 ? _max_clnt : 65535);
    if(listen(insoc->socketFd(),_max) == -1)
    {
        insoc->closeSocket();
        delete insoc;
        insoc = 0;
        _errno = SE_LISTEN;
        return false;
    }
    efd = epoll_create1(0);
    if( efd == -1)
    {
        insoc->closeSocket();
        delete insoc;
        insoc = 0;
        _errno = SE_LISTEN;
        return false;
    }

    event.data.fd = insoc->socketFd();
    event.events = EPOLLIN | EPOLLOUT | EPOLLET;
    if(epoll_ctl(efd,EPOLL_CTL_ADD,insoc->socketFd(),&event) == -1)
    {
        insoc->closeSocket();
        _errno = SE_EPOOL;
        delete insoc;
        insoc = 0;
        return false;
    }
    events = (struct epoll_event *) malloc(_max*sizeof(struct epoll_event));

    mainloop();
}

bool RServer::isListening() const
{
    return _list_state;
}

void RServer::setMaxClients(int max)
{
    if( max < 0)
        return;

    _max_clnt = max;
}

void RServer::setAddressFamily(RAbstractSocket::AddressFamily af)
{
    _af = af;
}

void RServer::setProtocolFamily(RAbstractSocket::ProtocolFamyly pf)
{
    _pf = pf;
}

char* RServer::serverHost() const
{
    return _host;
}

uint16_t RServer::serverPort() const
{
    return _port;
}

int RServer::maxClients() const
{
    return _max_clnt;
}

int RServer::socketDescriptor() const
{
    if(!insoc)
        return 0;

    return insoc->socketFd();
}

void RServer::stop()
{
    _stop_flag = true;
}

void RServer::mainloop()
{

}

void RServer::addedNewClient(int socfd)
{

}

void RServer::canReadData(int socfd)
{

}

void RServer::canWriteData(int socfd)
{

}

void RServer::setListStatus(bool state)
{
    _list_state = state;
}

void RServer::setErrorCode(int ecode)
{
    _errno = ecode;
}

int RServer::error() const
{
    return _errno;
}

}